package com.taskinception;

import android.app.Activity;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.database.SQLException;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.taskinception.connectivity.DatabaseAdapter;
import com.taskinception.model.Task;
import com.taskinception.utils.Alert;

public class EditTaskActivity extends Activity {

    public static final String TAG_ID = "task_id";
    public static final String TAG_PARENT = "task_parent";

    private DatabaseAdapter mDbAdapter = null;

    private long mId = -1;
    private long mParent = 0;

    private EditText mTitleEditText;
    private EditText mBodyEditText;
    private Button mSaveButton;

    private Menu mMenu;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.task_edit);

        try {
            mDbAdapter = new DatabaseAdapter(this).open();
        } catch (SQLException e) {
            Toast.makeText(getApplicationContext(),
                    "Database error. Try again", Toast.LENGTH_SHORT).show();
            e.printStackTrace();
        }

        getActionBar().setDisplayHomeAsUpEnabled(true);
        mSaveButton = (Button) findViewById(R.id.task_save);
        setTitle("");

        populateFields();

        mTitleEditText.addTextChangedListener(new TextWatcher() {

            @Override
            public void beforeTextChanged(CharSequence sequence, int start,
                                          int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence sequence, int start,
                                      int count, int after) {
                validateForm();
            }

            @Override
            public void afterTextChanged(Editable sequence) {
            }

        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        getMenuInflater().inflate(R.menu.edit_task, menu);
        mMenu = menu;
        validateForm();
        return true;
    }

    @Override
    public boolean onMenuItemSelected(int featureId, MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_save:
                saveTask(item);
                return true;
            case android.R.id.home:
            case R.id.menu_cancel:
                // If any of the fields have a value, ask confirmation from the user
                cancelEditing();
                return true;
            default:
                return super.onMenuItemSelected(featureId, item);
        }
    }

    /**
     *
     */
    private void cancelEditing() {
        if (!mTitleEditText.getText().toString()
                .equals(mTitleEditText.getTag().toString())
                || !mBodyEditText.getText().toString()
                .equals(mBodyEditText.getTag().toString())) {
            Alert.confirm(EditTaskActivity.this, android.R.string.cancel,
                    R.string.cancel_sure_lost, new OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.dismiss();
                    finish();
                }
            }, null);
        } else {
            finish();
        }
    }

    /**
     * This method will we called when the user clicks the save button. Needed
     * because the Android framework will expect it to be there.
     *
     * @param view {@link View} it came from (save button)
     * @see #saveTask() saveTask()
     */
    public void saveTask(View view) {
        saveTask();
    }

    /**
     * This method will we called when the user clicks the save button in the
     * main menu. Needed because the Android framework will expect it to be
     * there.
     *
     * @param item {@link MenuItem} invoking this method
     */
    public void saveTask(MenuItem item) {
        saveTask();
    }

    /**
     * When the user input validates, update or create the {@link Task}. If it
     * does not validate, tell the user to enter at least a title
     */
    public void saveTask() {
        if (validateForm()) {

            final Task task;
            if (mId < 0) {
                // Create a new Task
                if (mParent >= 0) {
                    task = new Task(mTitleEditText.getText().toString(),
                            mBodyEditText.getText().toString());
                    task.setParent(mParent);
                } else {
                    task = new Task(mTitleEditText.getText().toString(),
                            mBodyEditText.getText().toString());
                }
                mId = mDbAdapter.createTask(task);

                // Directly go to the new Task, if it was inserted
                if (mId > -1) {
                    Intent intent = new Intent(EditTaskActivity.this,
                            TaskActivity.class);
                    intent.putExtra(TaskActivity.TAG_CURRENT_TASK, mId);
                    startActivity(intent);
                }
            } else {
                // Update the Task
                task = mDbAdapter.fetchTask(mId);
                task.setTitle(mTitleEditText.getText().toString());
                task.setBody(mBodyEditText.getText().toString());
                mDbAdapter.updateTask(task);
            }

            // Wrap up and close the current Activity
            finish();
        } else {
            // Probably dead code, because saving is only permitted when
            // validateForm() returns true. Just extra precautions to prevent
            // the task lists from cluttering up on empty tasks
            Alert.message(EditTaskActivity.this, R.string.save,
                    R.string.save_form_invalidates);
        }
    }

    /**
     * Retrieve values from the firing {@link Intent}, if available, and
     * populate the fields
     */
    private void populateFields() {
        mTitleEditText = (EditText) findViewById(R.id.task_title);
        mBodyEditText = (EditText) findViewById(R.id.task_body);

        Task task = new Task();

        Bundle extras = getIntent().getExtras();
        if (extras != null) {
            if (extras.containsKey(TAG_ID)) {
                mId = extras.getLong(TAG_ID);
                task = mDbAdapter.fetchTask(mId);
            }
            mParent = extras.getLong(TAG_PARENT, task.getParent());
        }

        mTitleEditText.setText(task.getTitle());
        mTitleEditText.setTag(task.getTitle());

        mBodyEditText.setText(task.getBody());
        mBodyEditText.setTag(task.getBody());

        // Request focus on the title, if empty. Otherwise, try the body
        if (mTitleEditText.getText().toString().isEmpty()) {
            mTitleEditText.requestFocus();
            setTitle(R.string.title_create_task);
        } else {
            mBodyEditText.requestFocus();
            setTitle(R.string.title_edit_task);
        }
        validateForm();
    }

    @Override
    public void onBackPressed() {
        cancelEditing();
    }

    /**
     * Perform form validation to determine if the save button(s) should be
     * enabled or disabled
     *
     * @return true if the form validated. False otherwise
     */
    private boolean validateForm() {
        boolean enabled = !mTitleEditText.getText().toString().isEmpty();
        mSaveButton.setEnabled(enabled);
        if (mMenu != null) {
            mMenu.findItem(R.id.menu_save).setEnabled(enabled);
        }
        return enabled;
    }
}
